package xyz.icxl.android.architecture.data

import com.squareup.moshi.JsonClass
import xyz.icxl.android.architecture.exception.RequestApiException
import xyz.icxl.android.architecture.helper.MoshiHelper

/**
 * 文件描述：通用的接口数据返回格式
 *
 * 文件创建人：cxl
 *
 * 创建时间：2021 年 11月 25 日
 *
 * 文件版本：v1.0
 *
 * 版本描述：创建文件
 */
@JsonClass(generateAdapter = true)
data class BRep<T>(
    /**
     * 业务码
     */
    val code: Int = -1,
    /**
     * 业务消息
     */
    val msg: String = "",
    /**
     * 数据
     */
    val data: T?,
) {
    companion object {
        var requestSuccessCode = 1
    }

    val success: Boolean
        get() = code == requestSuccessCode

    fun toJsonStr(): String {
        return "{\"msg\": \"$msg\",\"code\": $code,\"data\": ${MoshiHelper.toJsonStr(data)},}"
    }

}


sealed class ApiResult<out T : Any> {

    data class Success<out T : Any>(val data: T?) : ApiResult<T>()
    data class Error(val exception: Exception) : ApiResult<Nothing>()

    override fun toString(): String {
        return when (this) {
            is Success<*> -> "Success[data=$data]"
            is Error -> "Error[exception=$exception]"
        }
    }

}

inline fun <T : Any> ApiResult<T>.checkResult(
    success: (data: T?) -> Unit,
    error: (msg: String) -> Unit = {},
    errorSupper: (Int, String) -> Unit = { _, _ -> }
) {
    if (this is ApiResult.Success) {
        try {
            success(data)
        } catch (e: java.lang.Exception) {
            error("data resolve fail:${e.message}")
            e.printStackTrace()
        }
    } else if (this is ApiResult.Error) {
        error(exception.message ?: "request fail.")
        if (exception is RequestApiException)
            errorSupper(exception.code, exception.msg)
        else
            errorSupper(exception.hashCode(), exception.message ?: "request fail.")
    }
}


inline fun <T : Any> ApiResult<T>.checkResultCheckNull(
    success: (data: T) -> Unit,
    error: (msg: String) -> Unit = {},
    errorSupper: (Int, String) -> Unit = { _, _ -> }
) {
    if (this is ApiResult.Success) {
        try {
            if (data == null) {
                error("data resolve fail")
            } else {
                success(data)
            }
        } catch (e: java.lang.Exception) {
            error("data resolve fail:${e.message}")
            e.printStackTrace()
        }
    } else if (this is ApiResult.Error) {
        error(exception.message ?: "request fail.")
        if (exception is RequestApiException)
            errorSupper(exception.code, exception.msg)
        else
            errorSupper(exception.hashCode(), exception.message ?: "request fail.")
    }
}


inline fun <T : Any> ApiResult<T>.success(success: (T?) -> Unit): ApiResult<T> {
    if (this is ApiResult.Success) {
        success(data)
    }
    return this
}

inline fun <T : Any> ApiResult<T>.error(error: (Int, String) -> Unit): ApiResult<T> {
    if (this is ApiResult.Error) {
        if (exception is RequestApiException)
            error(exception.code, exception.msg)
        else
            error(exception.hashCode(), exception.message ?: "request fail.")
    }
    return this
}


inline fun <T : Any> ApiResult<T>.error(error: (String) -> Unit): ApiResult<T> {
    if (this is ApiResult.Error) {
        if (exception is RequestApiException)
            error(exception.msg)
        else
            error(exception.message ?: "request fail.")
    }
    return this
}